// 6函数模板和类模板.cpp : 定义控制台应用程序的入口点。
//


#include "Animal.h"
#include "Animal.cpp" //使用类模板，要把.cpp文件包含进来，所以写类模板时最好把函数的声明和实现都写在同一个文件中,命名为.hcpp文件
#include <iostream>
#include <string>
using namespace std;
//template 关键字告诉C++编译器 我要开始泛型了.你不要随便报错
//数据类型T 参数化数据类型
//函数模板(泛型)
//模板函数会严格按照数据类型匹配,不会发生隐式转换

/*
1 函数模板可以像普通函数一样被重载
2 C++编译器优先考虑普通函数
3 如果函数模板可以产生一个更好的匹配，那么选择模板
4 可以通过空模板实参列表的语法限定编译器只通过模板匹配
*/
template <typename T>
void my_swap(T &a, T &b)
{
	cout << "模板函数" << endl;
	T temp;
	temp = a;
	a = b;
	b = temp;
}
//普通函数类型可以进行隐式类型转换
void my_swap(int &a, int &b)
{
	cout << "普通函数" << endl;
	int temp = a;
	a = b;
	b = temp;
}
//使用函数模板，选择排序
template<typename T, typename T1>
void sort(T* arr, T1 length)
{
	for (int i = 0; i < length; i++)
	{
		for (int j = i + 1; j < length - 1; j++)
		{
			if (arr[i] > arr[j])
			{
				T temp = 0;
				temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
			}
		}
	}

	for (int i = 0; i < length; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
}

template<typename T>
class Student
{
public:
	Student(T t = 0)
	{
		cout << "Student类构造函数" << endl;
		this->t = t;
	}
	~Student()
	{
		cout << "Student析构函数" << endl;
	}
	T get_t()
	{
		return this->t;
	}
	void print_stu();
private:
	T t;
};
//模板函数写在类的外部
template<typename T>
void Student<T>::print_stu()
{
	cout << "打印Student" << endl;
}
/*
普通类继承模板类
*/
class MiddleStudent :public Student<int>
{
public:
	MiddleStudent(int a = 0) :Student(a)
	{
		cout << "MiddleStudent构造函数" << endl;
	}
	~MiddleStudent()
	{
		cout << "MiddleStudent析构函数" << endl;
	}
};
/*
模板类继承模板类
*/
template<typename T>
class HeighStudent :public Student<T>
{
public:
	HeighStudent(T t) :Student(t)
	{

	}
};
//使用模板函数
void fan_xing()
{
	int a = 10;
	int b = 30;
	int &a_1 = a;
	int &b_1 = b;

	//int类型可以使用泛型函数
	my_swap<int>(a_1, b_1);//显示类型调用(常用),调用模板函数,编译器会根据实际情况再生成与实际类型相符的函数
	cout << "a = " << a << "; b = " << b << endl; //交换a ,b的值

	my_swap(a_1, b_1);//优先调用普通函数
	cout << "a = " << a << "; b = " << b << endl; //交换a ,b的值

	//double类型也可以使用泛型函数
	double c = 12;
	double d = 45;
	double &c_1 = c;
	double &d_1 = d;
	my_swap(c_1, d_1);//自动类型推导(不常用)，调用模板函数
	cout << "c = " << c << "; d = " << d << endl; //交换c ,d的值
}

//模板函数排序
void fan_xing_sort()
{
	int arr[10] = { 23,45,8,4,23,9,6,23,67,90 };
	double arr1[10] = { 23.1,4.5,8.8,4.6,2.3,9.6,6.0,23.5,67.23,90.21 };
	sort<int, int>(arr, 10);
	sort<double, double>(arr1, 10);
}

//使用模板类
void template_class()
{
	/*Student<int> stu(23);
	cout << stu.get_t() << endl;*/

	//MiddleStudent middle_stu(15);
	//middle_stu.print_stu();
	//cout << middle_stu.get_t() << endl;

	/*HeighStudent<int> hei_stu(17);
	cout << hei_stu.get_t() << endl;*/

	Animal<int> a;
	a.set_t(34);
	cout << a.get_t() << endl;


}
int main5()
{

	//fan_xing();
	//fan_xing_sort();
	template_class();
	return 0;
}
